package smartcase.base.log;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.LoggerContextVO;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import com.google.common.collect.ImmutableSet;
import smartcase.base.ConfigurationDefine;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static smartcase.base.ApplicationContextProviderKt.getBean;
import static smartcase.common.util.NetUtils.getLocalIP;

public class LogbackAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {

  @Deprecated
  private static final Pattern pattern =
      Pattern.compile(
          "^(.|\\n)*commonLogCtx:requestId=\\[(.*)\\],\\spath=\\[(.*)\\],\\sendpoint=\\[(.*)\\],\\sextInfo=\\[(.*)\\]$");

  @Override
  protected void append(ILoggingEvent event) {
    ConfigurationDefine define;
    if ((define = getBean(ConfigurationDefine.class)) == null) return;

    LogStruct logStruct = new LogStruct();
    logStruct.setLevel(Optional.ofNullable(event.getLevel()).map(Level::toString).orElse(null));

    Matcher matcher = pattern.matcher(event.getFormattedMessage());
    boolean find = matcher.find();
    int matchCount = matcher.groupCount();
    if (find && matchCount >= 4) {
      logStruct.setRequestId(matcher.group(matchCount - 3));
      logStruct.setPath(matcher.group(matchCount - 2));
      logStruct.setEndpoint(matcher.group(matchCount - 1));
      logStruct.setExtInfo(matcher.group(matchCount));
    }

    String formattedMessage = event.getFormattedMessage();
    int i = formattedMessage.indexOf("| commonLogCtx : requestId=");
    if (i == -1) logStruct.setMessage(formattedMessage);
    if (i != -1) logStruct.setMessage(formattedMessage.substring(0, i));

    if (Level.ERROR.equals(event.getLevel())) {
      logStruct.setExceptionMsg(logStruct.getMessage());
      logStruct.setMessage("");
    }

    logStruct.setThreadName(event.getThreadName());
    logStruct.setModule(define.getModule());
    logStruct.setThreadName(event.getThreadName());
    logStruct.setTimestamp(event.getTimeStamp());
    logStruct.setServerIP(getLocalIP());

    StackTraceElement[] traceEles;
    if ((traceEles = event.getCallerData()) != null && traceEles.length >= 3) {
      StackTraceElement bizEle = traceEles[2];
      logStruct.setClassName(bizEle.getClassName());
      logStruct.setMethod(bizEle.getMethodName());
      logStruct.setFileName(bizEle.getFileName());
      logStruct.setLineNum(String.valueOf(bizEle.getLineNumber()));
    }

    LogReporter.submitLog(logStruct);
  }
}
